package com.app.baselibrary.base
import android.util.SparseIntArray
import android.view.View
import android.view.ViewGroup
import androidx.annotation.CallSuper
import androidx.annotation.IntRange
import androidx.annotation.LayoutRes
import com.app.baselibrary.R
import com.app.baselibrary.databinding.BaseItemAdapterEmptyBinding
import com.app.baselibrary.ktx.onClick
import com.app.baselibrary.ktx.onLongClick
import java.util.*
import androidx.recyclerview.widget.RecyclerView

/**
 * 适配器基础类
 */
abstract class BaseAdapter<T: DataType>(val showEmpty: Boolean = true) : RecyclerView.Adapter<BaseViewHolder>() {

    companion object {

        const val EMPTY_ITEM = -1
    }

    private var mRecyclerView: RecyclerView? = null

    private val viewTypes by lazy { SparseIntArray() }

    private val mData = ArrayList<T>()

    private var isLong:Boolean=true

    private var itemClickListener: (BaseAdapter<T>.(Int)->Unit)? = null

    override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
        super.onAttachedToRecyclerView(recyclerView)
        this.mRecyclerView = recyclerView
    }


    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
        if (viewType == EMPTY_ITEM && showEmpty){
            return BaseViewHolder(View.inflate(parent.context, R.layout.base_item_adapter_empty, null))
        }
        val itemLayout = viewTypes.get(viewType, R.layout.base_layout_item_default_adapter)
        return BaseViewHolder(View.inflate(parent.context, itemLayout, null))
    }

    override fun getItemCount(): Int {
        return if(mData.isEmpty() && showEmpty) 1 else mData.size
    }

    override fun getItemViewType(position: Int): Int {
        if (mData.isEmpty() && showEmpty){
            return EMPTY_ITEM
        }
        val dataType = mData[position]
        viewTypes.put(dataType.dataType(), dataType.layoutId())
        return dataType.dataType()
    }

    override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
        if (mData.isEmpty() && showEmpty){
            bindEmpty(BaseItemAdapterEmptyBinding.bind(holder.itemView))
            return
        }
        val data = mData[holder.bindingAdapterPosition]
        if(isLong){
            holder.itemView.onLongClick {
                itemClickListener?.invoke(this@BaseAdapter, holder.bindingAdapterPosition)
            }
        }else{
            holder.itemView.onClick {
                itemClickListener?.invoke(this@BaseAdapter, holder.bindingAdapterPosition)
            }
        }

        bindItem(data, holder,position)
    }

    @CallSuper
    open fun bindEmpty(viewBinding: BaseItemAdapterEmptyBinding){
        mRecyclerView?.apply {
            viewBinding.root.minHeight = measuredHeight
        }
    }

    abstract fun bindItem(data: T, holder: BaseViewHolder, position: Int)


    fun setOnItemClickListener(mLong:Boolean=true,action: BaseAdapter<T>.(Int)->Unit) = apply {
        this.itemClickListener = action
        this.isLong=mLong
    }

    fun setData(data: List<T>) = apply{
        this.mData.clear()
        this.mData.addAll(data)
        notifyDataSetChanged()
    }

    fun addData(data: List<T>) = apply {
        val start = this.mData.size
        this.mData.addAll(data)
        notifyItemRangeInserted(start, data.size)
    }

    fun addData(data: T) = apply {
        val start = this.mData.size
        this.mData.add(data)
        notifyItemRangeInserted(start, 1)
    }

    fun remove(data: T) = apply {
        var i = -1
        this.mData.forEachIndexed { index, t ->
            if (data == t){
                i = index
            }
        }
        if (i != -1){
            this.mData.removeAll(Collections.singletonList(data))
            notifyItemRemoved(i)
        }
    }

    fun removeNo(data: T) = apply {
        var i = -1
        this.mData.forEachIndexed { index, t ->
            if (data == t){
                i = index
            }
        }
        if (i != -1){
            this.mData.removeAll(Collections.singletonList(data))
        }
    }

    fun getData(position: Int): T = this.mData[position]

    fun clear() {
        this.mData.clear()
        notifyDataSetChanged()
    }

}


interface DataType{

    @IntRange(from = 1)
    fun dataType(): Int

    @LayoutRes
    fun layoutId(): Int
}


class BaseViewHolder(itemView: View): RecyclerView.ViewHolder(itemView)